<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>8球制台球小游戏</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        table: '#1a472a',
                        cushion: '#8b4513',
                        cue: '#deb887',
                        ball: '#ffffff',
                        'striped-ball': '#f5f5dc',
                        'black-ball': '#000000',
                        'player-1': '#ff0000',
                        'player-2': '#0000ff',
                    },
                    fontFamily: {
                        sans: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .shadow-cue {
                box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
            }
            .text-shadow {
                text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
            }
            .animate-pulse-slow {
                animation: pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite;
            }
        }
    </style>
</head>
<body class="bg-gray-900 text-white min-h-screen flex flex-col items-center justify-center p-4">
    <div class="max-w-6xl w-full mx-auto">
        <!-- 游戏标题 -->
        <h1 class="text-[clamp(2rem,5vw,3.5rem)] font-bold text-center mb-4 text-shadow">8球制台球</h1>
        
        <!-- 游戏状态和控制区 -->
        <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
            <div class="bg-gray-800 rounded-lg p-4 shadow-lg">
                <h2 class="text-xl font-bold mb-2 flex items-center">
                    <span id="player1-indicator" class="w-4 h-4 rounded-full bg-gray-500 mr-2"></span>
                    玩家 1 (全色)
                </h2>
                <div class="flex flex-wrap gap-1" id="player1-balls">
                    <!-- 玩家1的球会动态显示 -->
                </div>
            </div>
            
            <div class="bg-gray-800 rounded-lg p-4 shadow-lg text-center">
                <h2 class="text-xl font-bold mb-2">当前状态</h2>
                <p id="game-status" class="text-lg font-medium">准备开球</p>
                <p id="turn-indicator" class="text-sm text-gray-300">玩家 1 的回合</p>
                <button id="reset-btn" class="mt-2 px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded-md transition-all duration-200 hidden">
                    <i class="fa fa-refresh mr-1"></i> 重新开始
                </button>
                <button id="start-game-btn" class="mt-2 px-4 py-2 bg-green-600 hover:bg-green-700 rounded-md transition-all duration-200">
                    <i class="fa fa-play mr-1"></i> 开始游戏
                </button>
            </div>
            
            <div class="bg-gray-800 rounded-lg p-4 shadow-lg">
                <h2 class="text-xl font-bold mb-2 flex items-center">
                    <span id="player2-indicator" class="w-4 h-4 rounded-full bg-gray-500 mr-2"></span>
                    玩家 2 (花色)
                </h2>
                <div class="flex flex-wrap gap-1" id="player2-balls">
                    <!-- 玩家2的球会动态显示 -->
                </div>
            </div>
        </div>
        
        <!-- 台球桌 -->
        <div class="relative bg-table rounded-2xl shadow-xl overflow-hidden border-8 border-cushion">
            <canvas id="pool-table" class="w-full h-auto"></canvas>
            
            <!-- 控制滑块 -->
            <div id="power-control" class="absolute bottom-4 left-1/2 transform -translate-x-1/2 w-64 bg-gray-700/80 rounded-full p-2 flex items-center">
                <i class="fa fa-bolt text-yellow-400 mr-2"></i>
                <input type="range" id="power-slider" min="1" max="100" value="50" class="w-full h-2 bg-gray-500 rounded-lg appearance-none cursor-pointer">
                <span id="power-value" class="ml-2 text-sm font-medium">50%</span>
            </div>
            
            <!-- 游戏提示 -->
            <div id="game-instructions" class="absolute top-4 left-1/2 transform -translate-x-1/2 bg-black/60 rounded-full px-4 py-2 text-sm">
                点击并拖动白球后方来瞄准，松开击球
            </div>
        </div>
        
        <!-- 游戏规则说明 -->
        <div class="mt-6 bg-gray-800 rounded-lg p-4 shadow-lg">
            <h2 class="text-xl font-bold mb-2">游戏规则</h2>
            <ul class="list-disc pl-5 space-y-1 text-sm">
                <li>使用主球（白球）击打目标球，合法将8号球最后入袋的一方获胜</li>
                <li>玩家需先将自己组别的球（全色或花色）全部击入袋，再击打8号球</li>
                <li>开球后，首个合法进球的球组即为该玩家的目标球组</li>
                <li>合法击球必须先击中自己的目标球组，且任何球必须碰库边或有球进袋</li>
                <li>犯规情况包括主球落袋、未击中自己的目标球、无球碰库边且无球进袋</li>
                <li>主球落袋时，对手获自由球，可摆放在任意位置</li>
            </ul>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            // 获取Canvas元素和上下文
            const canvas = document.getElementById('pool-table');
            const ctx = canvas.getContext('2d');
            
            // 获取DOM元素
            const powerSlider = document.getElementById('power-slider');
            const powerValue = document.getElementById('power-value');
            const gameStatus = document.getElementById('game-status');
            const turnIndicator = document.getElementById('turn-indicator');
            const player1Indicator = document.getElementById('player1-indicator');
            const player2Indicator = document.getElementById('player2-indicator');
            const player1Balls = document.getElementById('player1-balls');
            const player2Balls = document.getElementById('player2-balls');
            const resetBtn = document.getElementById('reset-btn');
            const startGameBtn = document.getElementById('start-game-btn');
            const gameInstructions = document.getElementById('game-instructions');
            
            // 设置Canvas尺寸，根据屏幕宽度自适应
            function resizeCanvas() {
                const container = canvas.parentElement;
                const containerWidth = container.clientWidth;
                const aspectRatio = 2 / 1; // 台球桌比例
                canvas.width = containerWidth;
                canvas.height = containerWidth / aspectRatio;
                updateConfig(); // 调整尺寸后立即更新配置
                drawGame(); // 重新绘制
            }
            
            // 监听窗口大小变化
            window.addEventListener('resize', resizeCanvas);

            // 游戏配置（全局单例）
            const config = {
                ballRadius: 0,
                tablePadding: 0,
                pocketRadius: 0,
                friction: 0.98,
                minVelocity: 0.1,
                cueLength: 0,
                cueThickness: 0
            };

            // 袋口对象（依赖config，需在config初始化后创建）
            const pockets = [
                { x: 0, y: 0, radius: 0 },
                { x: 0, y: 0, radius: 0 },
                { x: 0, y: 0, radius: 0 },
                { x: 0, y: 0, radius: 0 },
                { x: 0, y: 0, radius: 0 },
                { x: 0, y: 0, radius: 0 }
            ];

            // 更新配置及袋口位置
            function updateConfig() {
                config.ballRadius = canvas.width / 60;
                config.tablePadding = canvas.width / 12;
                config.pocketRadius = canvas.width / 20;
                config.cueLength = canvas.width / 6;
                config.cueThickness = canvas.width / 120;

                // 更新袋口坐标
                pockets[0] = { 
                    x: config.tablePadding, 
                    y: config.tablePadding, 
                    radius: config.pocketRadius 
                };
                pockets[1] = { 
                    x: canvas.width / 2, 
                    y: config.tablePadding, 
                    radius: config.pocketRadius 
                };
                pockets[2] = { 
                    x: canvas.width - config.tablePadding, 
                    y: config.tablePadding, 
                    radius: config.pocketRadius 
                };
                pockets[3] = { 
                    x: config.tablePadding, 
                    y: canvas.height - config.tablePadding, 
                    radius: config.pocketRadius 
                };
                pockets[4] = { 
                    x: canvas.width / 2, 
                    y: canvas.height - config.tablePadding, 
                    radius: config.pocketRadius 
                };
                pockets[5] = { 
                    x: canvas.width - config.tablePadding, 
                    y: canvas.height - config.tablePadding, 
                    radius: config.pocketRadius 
                };
            }

            // 球对象类
            class Ball {
                constructor(x, y, number, color, isStriped = false) {
                    this.x = x;
                    this.y = y;
                    this.number = number;
                    this.color = color;
                    this.isStriped = isStriped;
                    this.velocityX = 0;
                    this.velocityY = 0;
                    this.inPocket = false;
                    this.isWhiteBall = number === 0;
                }

                draw() {
                    if (this.inPocket) return;
                    
                    ctx.beginPath();
                    ctx.arc(this.x, this.y, config.ballRadius, 0, Math.PI * 2);
                    ctx.fillStyle = this.color;
                    ctx.fill();
                    
                    // 绘制球的边框
                    ctx.beginPath();
                    ctx.arc(this.x, this.y, config.ballRadius, 0, Math.PI * 2);
                    ctx.strokeStyle = 'rgba(0, 0, 0, 0.3)';
                    ctx.lineWidth = config.ballRadius / 10;
                    ctx.stroke();
                    
                    // 如果是白球，不绘制数字
                    if (this.isWhiteBall) return;
                    
                    // 绘制数字背景
                    ctx.beginPath();
                    ctx.arc(this.x, this.y, config.ballRadius * 0.4, 0, Math.PI * 2);
                    ctx.fillStyle = 'white';
                    ctx.fill();
                    
                    // 绘制数字
                    ctx.fillStyle = 'black';
                    ctx.font = `${config.ballRadius * 0.6}px Arial`;
                    ctx.textAlign = 'center';
                    ctx.textBaseline = 'middle';
                    ctx.fillText(this.number.toString(), this.x, this.y);
                }

                update() {
                    if (this.inPocket) return;
                    
                    // 应用摩擦力
                    this.velocityX *= config.friction;
                    this.velocityY *= config.friction;
                    
                    // 如果速度太小，停止移动
                    if (Math.abs(this.velocityX) < config.minVelocity) this.velocityX = 0;
                    if (Math.abs(this.velocityY) < config.minVelocity) this.velocityY = 0;
                    
                    // 更新位置
                    this.x += this.velocityX;
                    this.y += this.velocityY;
                    
                    // 检测与库边的碰撞
                    this.checkCushionCollision();
                    
                    // 检测是否落入袋中
                    this.checkPocketCollision();
                }

                checkCushionCollision() {
                    // 计算球的边界
                    const left = this.x - config.ballRadius;
                    const right = this.x + config.ballRadius;
                    const top = this.y - config.ballRadius;
                    const bottom = this.y + config.ballRadius;
                    
                    // 计算台球桌的边界（考虑库边厚度）
                    const tableLeft = config.tablePadding;
                    const tableRight = canvas.width - config.tablePadding;
                    const tableTop = config.tablePadding;
                    const tableBottom = canvas.height - config.tablePadding;
                    
                    // 检测左右库边碰撞
                    if (left <= tableLeft) {
                        this.x = tableLeft + config.ballRadius;
                        this.velocityX = -this.velocityX * 0.8; // 反弹并损失一些能量
                    } else if (right >= tableRight) {
                        this.x = tableRight - config.ballRadius;
                        this.velocityX = -this.velocityX * 0.8;
                    }
                    
                    // 检测上下库边碰撞
                    if (top <= tableTop) {
                        this.y = tableTop + config.ballRadius;
                        this.velocityY = -this.velocityY * 0.8;
                    } else if (bottom >= tableBottom) {
                        this.y = tableBottom - config.ballRadius;
                        this.velocityY = -this.velocityY * 0.8;
                    }
                }

                checkPocketCollision() {
                    // 检查是否落入任何袋中
                    for (const pocket of pockets) {
                        const dx = this.x - pocket.x;
                        const dy = this.y - pocket.y;
                        const distance = Math.sqrt(dx * dx + dy * dy);
                        
                        if (distance < pocket.radius - config.ballRadius * 0.8) {
                            this.inPocket = true;
                            this.velocityX = 0;
                            this.velocityY = 0;
                            
                            // 记录入袋的球
                            if (!this.isWhiteBall) {
                                gameState.ballsPocketed.push(this.number);
                                
                                // 更新玩家球的显示
                                updatePlayerBallsDisplay();
                                
                                // 检查游戏是否结束
                                checkGameEnd();
                            } else {
                                // 白球落袋，视为犯规
                                gameState.lastFoul = true;
                                gameState.canMoveWhite = true;
                                
                                // 更新状态显示
                                gameStatus.textContent = '白球落袋！对手获得自由球';
                                
                                // 重新放置白球到初始位置
                                setTimeout(() => {
                                    const whiteBall = balls[0];
                                    whiteBall.x = canvas.width / 3;
                                    whiteBall.y = canvas.height / 2;
                                    whiteBall.inPocket = false;
                                }, 500);
                            }
                            
                            break;
                        }
                    }
                }
            }

            // 球的数组
            let balls = [];

            // 初始化球
            function initBalls() {
                balls = [];
                
                // 创建白球（主球）
                const whiteBall = new Ball(
                    canvas.width / 3,
                    canvas.height / 2,
                    0,
                    'white'
                );
                balls.push(whiteBall);
                
                // 创建其他球（1-15号）
                const ballDefinitions = [
                    { number: 1, color: '#FEF200', isStriped: false }, // 黄球
                    { number: 2, color: '#0066B3', isStriped: false }, // 蓝球
                    { number: 3, color: '#E61E2A', isStriped: false }, // 红球
                    { number: 4, color: '#7D2A87', isStriped: false }, // 紫球
                    { number: 5, color: '#F68C1F', isStriped: false }, // 橙球
                    { number: 6, color: '#009B49', isStriped: false }, // 绿球
                    { number: 7, color: '#A6192E', isStriped: false }, // 棕球
                    { number: 8, color: '#000000', isStriped: false }, // 黑球
                    { number: 9, color: '#FEF200', isStriped: true },  // 黄球（花色）
                    { number: 10, color: '#0066B3', isStriped: true },  // 蓝球（花色）
                    { number: 11, color: '#E61E2A', isStriped: true },  // 红球（花色）
                    { number: 12, color: '#7D2A87', isStriped: true },  // 紫球（花色）
                    { number: 13, color: '#F68C1F', isStriped: true },  // 橙球（花色）
                    { number: 14, color: '#009B49', isStriped: true },  // 绿球（花色）
                    { number: 15, color: '#A6192E', isStriped: true }   // 棕球（花色）
                ];
                
                // 三角形排列的起始位置
                const startX = canvas.width * 2/3;
                const startY = canvas.height / 2;
                const spacing = config.ballRadius * 2.1;
                
                // 按照三角形排列放置球
                let ballIndex = 0;
                for (let row = 0; row < 5; row++) {
                    for (let col = 0; col <= row; col++) {
                        if (ballIndex >= ballDefinitions.length) break;
                        
                        // 计算每个球的位置
                        const x = startX - row * spacing * Math.sin(Math.PI/6);
                        const y = startY + (col - row/2) * spacing;
                        
                        // 创建球并添加到数组
                        const ballDef = ballDefinitions[ballIndex];
                        const ball = new Ball(x, y, ballDef.number, ballDef.color, ballDef.isStriped);
                        balls.push(ball);
                        ballIndex++;
                    }
                }
            }

            // 游戏状态
            const gameState = {
                isRunning: false,
                currentPlayer: 1, // 1或2
                player1Balls: [1, 2, 3, 4, 5, 6, 7],
                player2Balls: [9, 10, 11, 12, 13, 14, 15],
                player1Type: null, // 'solid'或'striped'
                player2Type: null,
                isGameStarted: false,
                isBreakShot: true,
                canMoveWhite: false, // 自由球状态
                ballsPocketed: [],
                lastFoul: false,
                cueAngle: 0, // 球杆角度（弧度）
                isAiming: false, // 是否正在瞄准
                aimStartX: 0,
                aimStartY: 0
            };

            // 绘制台球桌
            function drawTable() {
                // 绘制台面
                ctx.fillStyle = '#1a472a';
                ctx.fillRect(
                    config.tablePadding, 
                    config.tablePadding, 
                    canvas.width - config.tablePadding * 2, 
                    canvas.height - config.tablePadding * 2
                );
                
                // 绘制袋口
                for (const pocket of pockets) {
                    ctx.beginPath();
                    ctx.arc(pocket.x, pocket.y, pocket.radius, 0, Math.PI * 2);
                    ctx.fillStyle = '#333';
                    ctx.fill();
                }
                
                // 绘制库边
                ctx.fillStyle = '#8b4513';
                
                // 上边
                ctx.fillRect(
                    0, 
                    0, 
                    canvas.width, 
                    config.tablePadding
                );
                
                // 下边
                ctx.fillRect(
                    0, 
                    canvas.height - config.tablePadding, 
                    canvas.width, 
                    config.tablePadding
                );
                
                // 左边
                ctx.fillRect(
                    0, 
                    config.tablePadding, 
                    config.tablePadding, 
                    canvas.height - config.tablePadding * 2
                );
                
                // 右边
                ctx.fillRect(
                    canvas.width - config.tablePadding, 
                    config.tablePadding, 
                    config.tablePadding, 
                    canvas.height - config.tablePadding * 2
                );
            }

            // 绘制球杆
            function drawCue() {
                if (gameState.isAiming) {
                    const whiteBall = balls[0];
                    if (whiteBall.inPocket) return;
                    
                    ctx.beginPath();
                    
                    // 计算球杆的端点
                    const angle = gameState.cueAngle;
                    const distanceFromBall = config.ballRadius + 5;
                    const endX = whiteBall.x - Math.cos(angle) * (config.cueLength + distanceFromBall);
                    const endY = whiteBall.y - Math.sin(angle) * (config.cueLength + distanceFromBall);
                    
                    // 绘制球杆
                    ctx.moveTo(endX, endY);
                    ctx.lineTo(whiteBall.x - Math.cos(angle) * distanceFromBall, 
                               whiteBall.y - Math.sin(angle) * distanceFromBall);
                    
                    ctx.lineWidth = config.cueThickness;
                    ctx.strokeStyle = '#deb887';
                    ctx.stroke();
                    
                    // 绘制瞄准线
                    ctx.beginPath();
                    ctx.moveTo(whiteBall.x, whiteBall.y);
                    ctx.lineTo(whiteBall.x + Math.cos(angle) * 1000, 
                               whiteBall.y + Math.sin(angle) * 1000);
                    
                    ctx.lineWidth = 1;
                    ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';
                    ctx.setLineDash([5, 5]);
                    ctx.stroke();
                    ctx.setLineDash([]);
                }
            }

            // 更新玩家球的显示
            function updatePlayerBallsDisplay() {
                // 清空显示
                player1Balls.innerHTML = '';
                player2Balls.innerHTML = '';
                
                // 显示玩家1的球
                for (const ballNumber of gameState.player1Balls) {
                    if (!gameState.ballsPocketed.includes(ballNumber)) {
                        const ballEl = document.createElement('div');
                        ballEl.className = 'w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold';
                        
                        // 根据球号获取颜色
                        const ballDef = getBallDefinition(ballNumber);
                        if (ballDef) {
                            ballEl.style.backgroundColor = ballDef.color;
                            ballEl.textContent = ballNumber;
                        }
                        
                        player1Balls.appendChild(ballEl);
                    }
                }
                
                // 显示玩家2的球
                for (const ballNumber of gameState.player2Balls) {
                    if (!gameState.ballsPocketed.includes(ballNumber)) {
                        const ballEl = document.createElement('div');
                        ballEl.className = 'w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold';
                        
                        // 根据球号获取颜色
                        const ballDef = getBallDefinition(ballNumber);
                        if (ballDef) {
                            ballEl.style.backgroundColor = ballDef.color;
                            ballEl.textContent = ballNumber;
                        }
                        
                        player2Balls.appendChild(ballEl);
                    }
                }
            }

            // 获取球的定义
            function getBallDefinition(number) {
                const ballDefinitions = [
                    { number: 1, color: '#FEF200', isStriped: false },
                    { number: 2, color: '#0066B3', isStriped: false },
                    { number: 3, color: '#E61E2A', isStriped: false },
                    { number: 4, color: '#7D2A87', isStriped: false },
                    { number: 5, color: '#F68C1F', isStriped: false },
                    { number: 6, color: '#009B49', isStriped: false },
                    { number: 7, color: '#A6192E', isStriped: false },
                    { number: 8, color: '#000000', isStriped: false },
                    { number: 9, color: '#FEF200', isStriped: true },
                    { number: 10, color: '#0066B3', isStriped: true },
                    { number: 11, color: '#E61E2A', isStriped: true },
                    { number: 12, color: '#7D2A87', isStriped: true },
                    { number: 13, color: '#F68C1F', isStriped: true },
                    { number: 14, color: '#009B49', isStriped: true },
                    { number: 15, color: '#A6192E', isStriped: true }
                ];
                
                return ballDefinitions.find(ball => ball.number === number);
            }

            // 更新回合指示器
            function updateTurnIndicator() {
                if (gameState.currentPlayer === 1) {
                    player1Indicator.style.backgroundColor = '#ff0000';
                    player2Indicator.style.backgroundColor = '#444';
                    turnIndicator.textContent = '玩家 1 的回合';
                } else {
                    player1Indicator.style.backgroundColor = '#444';
                    player2Indicator.style.backgroundColor = '#0000ff';
                    turnIndicator.textContent = '玩家 2 的回合';
                }
            }

            // 检查球之间的碰撞
            function checkBallCollisions() {
                const whiteBall = balls[0];
                
                for (let i = 0; i < balls.length; i++) {
                    const ballA = balls[i];
                    
                    if (ballA.inPocket) continue;
                    
                    for (let j = i + 1; j < balls.length; j++) {
                        const ballB = balls[j];
                        
                        if (ballB.inPocket) continue;
                        
                        // 计算两球之间的距离
                        const dx = ballB.x - ballA.x;
                        const dy = ballB.y - ballA.y;
                        const distance = Math.sqrt(dx * dx + dy * dy);
                        
                        // 如果两球相撞
                        if (distance < config.ballRadius * 2) {
                            // 计算碰撞法线方向
                            const nx = dx / distance;
                            const ny = dy / distance;
                            
                            // 计算相对速度
                            const dvx = ballB.velocityX - ballA.velocityX;
                            const dvy = ballB.velocityY - ballA.velocityY;
                            
                            // 计算速度在法线方向上的投影
                            const dotProduct = dvx * nx + dvy * ny;
                            
                            // 如果两球正在远离，不处理碰撞
                            if (dotProduct > 0) continue;
                            
                            // 计算碰撞后的速度变化
                            const impulse = (2 * dotProduct) / (1 + 1); // 假设两球质量相同
                            
                            // 更新球的速度
                            ballA.velocityX -= impulse * nx;
                            ballA.velocityY -= impulse * ny;
                            ballB.velocityX += impulse * nx;
                            ballB.velocityY += impulse * ny;
                            
                            // 防止球重叠
                            const overlap = config.ballRadius * 2 - distance;
                            const correctionFactor = 0.5; // 调整修正量
                            
                            if (!ballA.isWhiteBall) {
                                ballA.x -= nx * overlap * correctionFactor;
                                ballA.y -= ny * overlap * correctionFactor;
                            }
                            
                            if (!ballB.isWhiteBall) {
                                ballB.x += nx * overlap * correctionFactor;
                                ballB.y += ny * overlap * correctionFactor;
                            }
                            
                            // 记录第一次白球碰撞的球
                            if (gameState.isRunning && ballA.isWhiteBall && !gameState.firstCollision && !ballB.isWhiteBall) {
                                gameState.firstCollision = ballB.number;
                            } else if (gameState.isRunning && ballB.isWhiteBall && !gameState.firstCollision && !ballA.isWhiteBall) {
                                gameState.firstCollision = ballA.number;
                            }
                        }
                    }
                }
            }

            // 检查是否有球碰库边
            function checkCushionContact() {
                // 白球碰库边不算
                for (let i = 1; i < balls.length; i++) {
                    const ball = balls[i];
                    
                    if (ball.inPocket) continue;
                    
                    // 计算球的边界
                    const left = ball.x - config.ballRadius;
                    const right = ball.x + config.ballRadius;
                    const top = ball.y - config.ballRadius;
                    const bottom = ball.y + config.ballRadius;
                    
                    // 计算台球桌的边界
                    const tableLeft = config.tablePadding;
                    const tableRight = canvas.width - config.tablePadding;
                    const tableTop = config.tablePadding;
                    const tableBottom = canvas.height - config.tablePadding;
                    
                    // 检测是否碰库边
                    if (left <= tableLeft || right >= tableRight || top <= tableTop || bottom >= tableBottom) {
                        return true;
                    }
                }
                
                return false;
            }

            // 检查游戏是否结束
            function checkGameEnd() {
                const whiteBall = balls[0];
                const blackBall = balls.find(ball => ball.number === 8);
                
                // 如果黑球入袋
                if (blackBall && blackBall.inPocket) {
                    // 检查是否犯规
                    if (gameState.lastFoul || whiteBall.inPocket) {
                        // 当前玩家输掉游戏
                        const winner = gameState.currentPlayer === 1 ? 2 : 1;
                        gameStatus.textContent = `玩家 ${winner} 获胜！`;
                        gameState.isRunning = false;
                        resetBtn.classList.remove('hidden');
                        startGameBtn.classList.add('hidden');
                        return true;
                    }
                    
                    // 检查玩家是否已经打完所有自己的球
                    const currentPlayerBalls = gameState.currentPlayer === 1 ? gameState.player1Balls : gameState.player2Balls;
                    const allPlayerBallsPocketed = currentPlayerBalls.every(ball => gameState.ballsPocketed.includes(ball));
                    
                    if (allPlayerBallsPocketed) {
                        // 当前玩家获胜
                        gameStatus.textContent = `玩家 ${gameState.currentPlayer} 获胜！`;
                        gameState.isRunning = false;
                        resetBtn.classList.remove('hidden');
                        startGameBtn.classList.add('hidden');
                        return true;
                    } else {
                        // 当前玩家输掉游戏（未打完自己的球就打进黑球）
                        const winner = gameState.currentPlayer === 1 ? 2 : 1;
                        gameStatus.textContent = `玩家 ${winner} 获胜！`;
                        gameState.isRunning = false;
                        resetBtn.classList.remove('hidden');
                        startGameBtn.classList.add('hidden');
                        return true;
                    }
                }
                
                return false;
            }

            // 处理击球后逻辑
            function handleShotComplete() {
                // 如果游戏已经结束，不处理
                if (checkGameEnd()) return;
                
                const whiteBall = balls[0];
                let isFoul = gameState.lastFoul;
                gameState.lastFoul = false;
                
                // 检查是否有合法进球
                let hasLegalPocket = false;
                
                // 开球阶段
                if (gameState.isBreakShot) {
                    // 检查开球是否打进至少一个球
                    const nonWhiteBallsPocketed = gameState.ballsPocketed.filter(ball => ball !== 0 && ball !== 8);
                    
                    if (nonWhiteBallsPocketed.length > 0) {
                        // 确定玩家类型
                        const firstPocketedBall = nonWhiteBallsPocketed[0];
                        const ballDef = getBallDefinition(firstPocketedBall);
                        
                        if (ballDef) {
                            const ballType = ballDef.isStriped ? 'striped' : 'solid';
                            
                            if (gameState.currentPlayer === 1) {
                                gameState.player1Type = ballType;
                                gameState.player2Type = ballType === 'striped' ? 'solid' : 'striped';
                            } else {
                                gameState.player2Type = ballType;
                                gameState.player1Type = ballType === 'striped' ? 'solid' : 'striped';
                            }
                            
                            hasLegalPocket = true;
                        }
                    }
                    
                    // 开球阶段结束
                    gameState.isBreakShot = false;
                } else {
                    // 非开球阶段
                    if (gameState.firstCollision) {
                        // 检查是否先击中自己的球
                        const currentPlayerBalls = gameState.currentPlayer === 1 ? gameState.player1Balls : gameState.player2Balls;
                        
                        if (!currentPlayerBalls.includes(gameState.firstCollision)) {
                            isFoul = true;
                        }
                        
                        // 检查是否有打进自己的球
                        const currentPlayerPocketedBalls = gameState.ballsPocketed.filter(ball => currentPlayerBalls.includes(ball));
                        
                        if (currentPlayerPocketedBalls.length > 0) {
                            hasLegalPocket = true;
                        }
                    } else {
                        // 没有碰撞任何球，犯规
                        isFoul = true;
                    }
                    
                    // 检查是否有球碰库边或有球进袋
                    const hasCushionContact = checkCushionContact();
                    const hasNonWhiteBallPocketed = gameState.ballsPocketed.some(ball => ball !== 0);
                    
                    if (!hasCushionContact && !hasNonWhiteBallPocketed) {
                        isFoul = true;
                    }
                }
                
                // 重置击球状态
                gameState.isRunning = false;
                gameState.firstCollision = null;
                
                // 如果白球落袋，视为犯规
                if (whiteBall.inPocket) {
                    isFoul = true;
                    gameState.canMoveWhite = true;
                    
                    // 重新放置白球到初始位置
                    setTimeout(() => {
                        whiteBall.x = canvas.width / 3;
                        whiteBall.y = canvas.height / 2;
                        whiteBall.inPocket = false;
                    }, 500);
                }
                
                // 更新状态显示
                if (isFoul) {
                    gameStatus.textContent = `犯规！玩家 ${gameState.currentPlayer === 1 ? 2 : 1} 的回合`;
                    
                    // 切换玩家
                    gameState.currentPlayer = gameState.currentPlayer === 1 ? 2 : 1;
                } else if (hasLegalPocket) {
                    // 继续当前玩家的回合
                    gameStatus.textContent = `玩家 ${gameState.currentPlayer} 继续击球`;
                } else {
                    // 切换玩家
                    gameState.currentPlayer = gameState.currentPlayer === 1 ? 2 : 1;
                    gameStatus.textContent = `玩家 ${gameState.currentPlayer} 的回合`;
                }
                
                // 清空本次击球打进的球
                gameState.ballsPocketed = [];
                
                // 更新回合指示器
                updateTurnIndicator();
                
                // 如果游戏没有结束，允许继续击球
                if (!checkGameEnd()) {
                    gameState.isAiming = true;
                }
            }

            // 绘制游戏
            function drawGame() {
                // 清空画布
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                
                // 绘制台球桌
                drawTable();
                
                // 绘制所有球
                for (const ball of balls) {
                    ball.draw();
                }
                
                // 绘制球杆
                drawCue();
            }

            // 游戏循环
            function gameLoop() {
                // 检查是否所有球都停止运动
                let allBallsStopped = true;
                
                for (const ball of balls) {
                    if (!ball.inPocket) {
                        ball.update();
                        
                        if (Math.abs(ball.velocityX) > config.minVelocity || 
                            Math.abs(ball.velocityY) > config.minVelocity) {
                            allBallsStopped = false;
                        }
                    }
                }
                
                // 检查球之间的碰撞
                checkBallCollisions();
                
                // 绘制游戏
                drawGame();
                
                // 如果所有球都停止运动，且游戏正在运行，处理击球完成
                if (allBallsStopped && gameState.isRunning) {
                    handleShotComplete();
                }
                
                // 继续游戏循环
                requestAnimationFrame(gameLoop);
            }

            // 初始化游戏
            function initGame() {
                resizeCanvas();
                initBalls();
                updatePlayerBallsDisplay();
                updateTurnIndicator();
                
                // 开始游戏循环
                gameLoop();
                
                // 游戏尚未开始
                gameState.isGameStarted = false;
                gameState.isRunning = false;
                gameState.isAiming = false;
                gameState.currentPlayer = 1;
                gameState.player1Type = null;
                gameState.player2Type = null;
                gameState.isBreakShot = true;
                gameState.canMoveWhite = false;
                gameState.lastFoul = false;
                
                gameStatus.textContent = '准备开球';
                resetBtn.classList.add('hidden');
                startGameBtn.classList.remove('hidden');
            }

            // 开始游戏
            function startGame() {
                if (!gameState.isGameStarted) {
                    gameState.isGameStarted = true;
                    gameState.isAiming = true;
                    gameStatus.textContent = '玩家 1 的开球';
                    startGameBtn.classList.add('hidden');
                }
            }

            // 重置游戏
            function resetGame() {
                initGame();
            }

            // 事件监听 - 力量滑块
            powerSlider.addEventListener('input', () => {
                powerValue.textContent = `${powerSlider.value}%`;
            });

            // 事件监听 - 开始游戏按钮
            startGameBtn.addEventListener('click', startGame);

            // 事件监听 - 重置游戏按钮
            resetBtn.addEventListener('click', resetGame);

            // 事件监听 - 鼠标按下（瞄准开始）
            canvas.addEventListener('mousedown', (e) => {
                if (!gameState.isAiming || gameState.isRunning) return;
                
                const rect = canvas.getBoundingClientRect();
                const mouseX = e.clientX - rect.left;
                const mouseY = e.clientY - rect.top;
                
                const whiteBall = balls[0];
                
                // 如果处于自由球状态，可以移动白球
                if (gameState.canMoveWhite) {
                    // 检查鼠标是否在白球上
                    const dx = mouseX - whiteBall.x;
                    const dy = mouseY - whiteBall.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    
                    if (distance <= config.ballRadius) {
                        gameState.isMovingWhite = true;
                    }
                } else {
                    // 计算球杆角度
                    const dx = mouseX - whiteBall.x;
                    const dy = mouseY - whiteBall.y;
                    gameState.cueAngle = Math.atan2(dy, dx);
                    gameState.isAiming = true;
                    gameState.aimStartX = mouseX;
                    gameState.aimStartY = mouseY;
                }
            });

            // 事件监听 - 鼠标移动
            canvas.addEventListener('mousemove', (e) => {
                if (!gameState.isAiming || gameState.isRunning) return;
                
                const rect = canvas.getBoundingClientRect();
                const mouseX = e.clientX - rect.left;
                const mouseY = e.clientY - rect.top;
                
                const whiteBall = balls[0];
                
                // 如果处于自由球状态且正在移动白球
                if (gameState.canMoveWhite && gameState.isMovingWhite) {
                    // 确保白球在台面上
                    const tableLeft = config.tablePadding + config.ballRadius;
                    const tableRight = canvas.width - config.tablePadding - config.ballRadius;
                    const tableTop = config.tablePadding + config.ballRadius;
                    const tableBottom = canvas.height - config.tablePadding - config.ballRadius;
                    
                    whiteBall.x = Math.max(tableLeft, Math.min(tableRight, mouseX));
                    whiteBall.y = Math.max(tableTop, Math.min(tableBottom, mouseY));
                    
                    return;
                }
                
                // 计算球杆角度
                const dx = mouseX - whiteBall.x;
                const dy = mouseY - whiteBall.y;
                gameState.cueAngle = Math.atan2(dy, dx);
            });

            // 事件监听 - 鼠标释放（击球）
            canvas.addEventListener('mouseup', (e) => {
                if (!gameState.isAiming || gameState.isRunning) return;
                
                const rect = canvas.getBoundingClientRect();
                const mouseX = e.clientX - rect.left;
                const mouseY = e.clientY - rect.top;
                
                const whiteBall = balls[0];
                
                // 如果处于自由球状态且移动了白球
                if (gameState.canMoveWhite && gameState.isMovingWhite) {
                    gameState.isMovingWhite = false;
                    gameState.canMoveWhite = false;
                    gameStatus.textContent = `玩家 ${gameState.currentPlayer} 的回合`;
                    return;
                }
                
                // 计算击球力量
                const aimEndX = mouseX;
                const aimEndY = mouseY;
                const power = powerSlider.value / 100;
                
                // 计算击球方向和力度
                const dx = whiteBall.x - aimEndX;
                const dy = whiteBall.y - aimEndY;
                const distance = Math.sqrt(dx * dx + dy * dy);
                
                // 只有当有足够的距离时才击球
                if (distance > config.ballRadius * 2) {
                    const maxForce = 15;
                    const force = Math.min(distance / 10, maxForce) * power;
                    
                    // 设置白球速度
                    whiteBall.velocityX = (dx / distance) * force;
                    whiteBall.velocityY = (dy / distance) * force;
                    
                    // 开始游戏
                    gameState.isRunning = true;
                    gameState.isAiming = false;
                    
                    // 更新状态显示
                    gameStatus.textContent = '击球中...';
                }
            });

            // 初始化游戏
            initGame();
        });
    </script>
</body>
</html>
    